from problem import ProblemState, ProblemAction
from Quoridor_game import DIRECTIONS, GetNextLocation, WHITE

class Astar_State(ProblemState):

    def __init__(self, target, myLocation, gameState, wantedPlayer):
        '''
        Constructor
        @param parameter: description.
        '''
        self.brdSize = gameState.brdSize
        self.target = target
        self.wantedPlayer = wantedPlayer
        self.myLocation = myLocation
        if wantedPlayer == WHITE:
            self.rivalLocations = gameState.locationsB # [tuple(x,y)...]
        else:
            self.rivalLocations = gameState.locationsW # [tuple(x,y)...]
        self.state = gameState        
      
    def getSuccessors(self):
        '''
        Generates all the actions that can be performed from this state, and
        the States those actions will create.
        
        @return: A dictionary containing each action as a key, and its state.
        '''
        successors = {}

        # Move actions       
        for direction in DIRECTIONS:                        
            nextLoc = GetNextLocation(self.myLocation, direction)
            nextRow = nextLoc[0]
            nextCol = nextLoc[1]   
            
            #moves out of board
            if nextRow < 0 or nextRow >= self.brdSize or nextCol < 0 or nextCol >= self.brdSize:
                continue
            #move illegal because of wall
            if not self.state._moveOkByWalls(direction, nextRow, nextCol):
                continue

            newLocation = nextLoc
            successors[Astar_Action(direction)] = Astar_State(self.target, newLocation, self.state, self.wantedPlayer)
            
        return successors
        

    def isGoal(self):
        '''
        @return: Whether this Problem state is the searched goal or not.
        '''
#        print "GOAL mylocation", self.myLocation
        if self.myLocation is None: return True
        if self.wantedPlayer == WHITE:
            return self.myLocation[0] >= self.brdSize-1 or self.myLocation[0] >= self.target
        else:
            return self.myLocation[0] <= 0 or self.myLocation[0] <= self.target
        
        
    def __cmp__(self, other):
        '''
        The comparison method must be implemented to ensure deterministic results.
        @return: Negative if self < other, zero if self == other and strictly 
        positive if self > other.
        '''        
        return cmp(self.myLocation, other.myLocation)
    
    def __hash__(self):
        '''
        The hash method must be implemented for states to be inserted into sets 
        and dictionaries.
        @return: The hash value of the state.
        '''
        return hash(self.myLocation)
        
    def __str__(self):
        s = "target: " +  str(self.target)
        s += ", location: " + str(self.myLocation)
        return s
        
class Astar_Action(ProblemAction):
    '''
    classdocs
    '''
    LegalMoves = ('S', 'N', 'W', 'E')

    def __init__(self, move):
        '''
        Initiates this Action with a cost.
        Default cost is 1.
        
        @param cost: (Optional) the cost of this Action. Default is 1.
        '''
        ProblemAction.__init__(self)
        self.move = move
        
    def __cmp__(self, other):
        return cmp(self.move, other.move)
    
    def __hash__(self):
        return hash(self.move)
    
    def __str__(self):
        retStr = ''
        if self.move == 'S':
            retStr += 'moved to south'
        if self.move == 'N':
            retStr += 'moved to north'
        elif self.move == 'W':
            retStr += 'moved to west'
        elif self.move == 'E':
            retStr += 'moved to east'
        return retStr


